定期ミートアップ 第51回
やりたいこと
Pair<Int, Bool>.new(1, true)を、
Pair.new(1, true)と書けるようにしたい
そのためにまず
Pair.new<Int, Bool>(1, true) と書けるようにした
これはHIR生成時に、
Pair<Int, Bool>.new(1, true) に置き換えられる
そこで問題が見つかった
code:sk
class X
def my_pair<A, B>(a: A, b: B) -> Pair<A, B>
Pair.new(a, b)
end
end
これはPair.new<A, B>(a, b)と推論できる
それはPair<A, B>.new(a, b)に置き換えられる
Pair.<>(A, B) → Pair<A, B>
となると、p Aができないといけない
どうするか
llvm関数の末尾に、AとBを受け取る引数を追加した
code:llvm
define %Pair* @my_pair(a: %A*, b: %B*, A: %Meta:Object*, B: %Meta:Object*)
コーナーケース
lambda内でAを参照した場合
lambdaはメソッド本体と別のllvm関数になるので、工夫が必要
code:sk
class X
def my_pair<A, B>(a: A, b: B) -> Pair<A, B>
ary.each do
Pair.new(a, b) # ここでAが取れないといけない
変数のキャプチャと同様にする
たいへんだったところ
型を間違って変なllvm IRが吐かれる
captureの型が間違ってるとか
コーナーケース
ArrayやObjectはクラスオブジェクトに評価されるが、VoidやNoneは例外的に「唯一のインスタンス」に評価される(クラスオブジェクトはVoid.classのようにして取る)
HirMaker::get_class_objectがこれを考慮していなかったので直した